package com.zzw.basic.io.nio;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class ServerTest {

	private static ServerSocketChannel server;
	private int port = 8080;
	private ByteBuffer rcBuffer = ByteBuffer.allocate(1024);
	private ByteBuffer sendBuffer = ByteBuffer.allocate(1024);
	private static Selector selector;
	public Map<SelectionKey,String> msgs = new HashMap<SelectionKey,String>();
	
	public ServerTest(int port) throws IOException{
		this.port = port;
		server = ServerSocketChannel.open();
		server.socket().bind(new InetSocketAddress(port));
		server.configureBlocking(false);
		selector = Selector.open();
		server.register(selector, SelectionKey.OP_ACCEPT);
		System.out.println("服务端初始化完成");
	}
	
	public void listenter() throws IOException{
		while(true){
			int eventCount = selector.select();
			if(eventCount <= 0){
				continue;
			}
			Set<SelectionKey> selectedKeys = selector.selectedKeys();
			Iterator<SelectionKey> iterator = selectedKeys.iterator();
			while(iterator.hasNext()){
				process(iterator.next());
				iterator.remove();
			}
		}
	}
	
	private void process(SelectionKey key){
		SocketChannel channel = null;
		try {
			if(key.isValid() && key.isAcceptable()){
				channel = server.accept();
				channel.configureBlocking(false);
				channel.register(selector, SelectionKey.OP_READ);
			}
			else if(key.isValid() && key.isReadable()){
				rcBuffer.clear();
				channel = (SocketChannel) key.channel();
				int len = channel.read(rcBuffer);
				if(len > 0){
					String msg = new String(rcBuffer.array(),0,len);
					System.out.println("服务端接受到的msg:" + msg);
					msgs.put(key, msg);
					channel.register(selector,SelectionKey.OP_WRITE);
				}
			}
			else if(key.isValid() && key.isWritable()){
				if(!msgs.containsKey(key)){
					return;
				}
				sendBuffer.clear();
				channel = (SocketChannel) key.channel();
				sendBuffer.put((new String(msgs.get(key) + "hello")).getBytes());
				sendBuffer.flip();//设置读取位
				channel.write(sendBuffer);
				channel.register(selector, SelectionKey.OP_READ);
			}
		} catch (Exception e) {
			
			try {
				key.cancel();
				channel.socket().close();
				channel.close();
			} catch (IOException e1) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) throws IOException {
		new ServerTest(8080).listenter();
	}
	
	public static void server(){
        ServerSocketChannel channel=null;  
        try{  
              
            Selector selector=Selector.open();  
            channel=ServerSocketChannel.open();  
            channel.configureBlocking(false);  
            channel.socket().setReuseAddress(true);   
            channel.bind(new InetSocketAddress(8020));  
            channel.register(selector, SelectionKey.OP_ACCEPT,new Integer(1));  
                  
            while(true){  
                if(selector.select()>0){  
                    Set<SelectionKey> sets=selector.selectedKeys();  
                    Iterator<SelectionKey> keys=sets.iterator();  
                    while(keys.hasNext()){  
                        SelectionKey key=keys.next();  
                        keys.remove();  
                        if(key.isAcceptable()){  
                            key.attach(new Integer(1));  
                            SocketChannel schannel=((ServerSocketChannel) key.channel()).accept();  
                            schannel.configureBlocking(false);  
                            schannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);  
                        }  
                        if(key.isReadable()){  
                            SocketChannel schannel = (SocketChannel) key.channel();  
                            ByteBuffer buf = ByteBuffer.allocate(1024);  
                            ByteArrayOutputStream output = new ByteArrayOutputStream();  
                            int len=0;  
                            while((len=schannel.read(buf))!=0){  
                                buf.flip();  
                                byte by[]=new byte[buf.remaining()];  
                                buf.get(by);  
                                output.write(by);  
                                buf.clear();  
                            }  
                            String str = new String(output.toByteArray());  
                            key.attach(str);  
                        }  
                        if(key.isWritable()){  
                            Object object=key.attachment();  
                            String attach=object!=null ? "server replay: "+object.toString() : "server replay: ";  
                            SocketChannel schannel=(SocketChannel) key.channel();  
                            schannel.write(ByteBuffer.wrap(attach.getBytes()));    
                        }  
                    }  
                }  
            }  
        }
        catch(Exception e){  
            e.printStackTrace();  
        }
        finally{  
            if(channel!=null){
                try {  
                    channel.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
    }  

}
